function AbstractPainter() {

	this.tracker = false;

	this.setTracker = function( tracker ) {
		this.tracker = tracker;
	}

	this.paintTestSuiteStart   	= function() {}
	this.paintTestSuiteEnd     	= function() {}
	this.paintTestCaseStart   	= function() {}
	this.paintTestCaseEnd     	= function() {}
	this.paintTestMethodStart	= function() {}
	this.paintTestMethodEnd 	= function() {}
	this.paintAssertionPass		= function( expectation ) {}
	this.paintAssertionFail		= function( expectation ) {}

}

function BasicPainter() {

	this.prototype = AbstractPainter();
	AbstractPainter.call( this );

	this.messageSeperator = '\r\n';
	this.failureMessages = new Array();

	this.setMessageSeperator = function( seperator ) {
		this.messageSeperator = seperator ;
	}
	
	this._outputTestSummary = function( message ) {
		if ( message ) 	alert( message );
	}
	
	this._outputTestFailures = function( message ) {
		if ( message ) 	alert( message );
	}

	this.paintTestSuiteEnd     = function() {

		var message = 'Test Complete:';

		message += this.messageSeperator;
		message += this.messageSeperator + 'Tests Cases ran: '		+ this.tracker.getTotalNumberOfTestCases();
		message += this.messageSeperator + 'Tests Cases passed: '	+ this.tracker.getTotalNumberOfTestCasesPassed();
		message += this.messageSeperator + 'Tests Cases failed: '	+ this.tracker.getTotalNumberOfTestCasesFailed();
		message += this.messageSeperator;
		message += this.messageSeperator + 'Test Methods ran: '		+ this.tracker.getTotalNumberOfTestMethods();
		message += this.messageSeperator + 'Test Methods passed: '	+ this.tracker.getTotalNumberOfTestMethodsPassed();
		message += this.messageSeperator + 'Test Methods failed: '	+ this.tracker.getTotalNumberOfTestMethodsFailed();
		message += this.messageSeperator;
		message += this.messageSeperator + 'Assertions passed: '	+ this.tracker.getTotalNumberOfAssertionsPassed();
		message += this.messageSeperator + 'Assertions failed: '	+ this.tracker.getTotalNumberOfAssertionsFailed();
		message += this.messageSeperator;
		
		this._outputTestSummary( message );
		
		var fullFailureMessage = '';
		for( var i=0; i<this.failureMessages.length; i++  ) {
			fullFailureMessage += this.messageSeperator + this.failureMessages[i];
		}
	
		this._outputTestFailures( fullFailureMessage );
	}
	
	this._getFailureMessage = function( expectation ) {
		return expectation.getAssertionMessage() + '\r\n'
				+ ' ' + expectation.getExpectationMessage() + ' '
				+ 'Expected: ' + expectation.getExpected() 
				+ ', Got: ' + expectation.getActual() + '\r\n\r\n';	
	}
	
	this.paintAssertionFail		= function( expectation ) {
	
		var message = this._getFailureMessage( expectation );
		
		var prefix = this.tracker.getCurrentTestCase() + '.' + this.tracker.getCurrentTestMethod();
	
		if ( message ) {
			message = prefix + ': ' + message;
		} else {
			message = prefix;
		}
		this.failureMessages[ this.failureMessages.length ] =  message;
	}
}

function HtmlPainter( tracker ) {

	HtmlPainter.prototype = new BasicPainter();
	BasicPainter.call( this, tracker );
	
	this.setMessageSeperator( '\r\n<br/>' );

	this._setDiv = function( divId, message ) {
		if ( message ) {
			var targetDiv = window.document.getElementById( divId );
			if ( targetDiv ) targetDiv.innerHTML = message;
		}
	}
	
	this._outputTestSummary = function( message ) {
		this._setDiv( 'TestSummary', message );
	}
	
	this._outputTestFailures = function( message ) {
		this._setDiv( 'TestFailures', message );
	}
}

function DocumentationPainter() {

	this.prototype = AbstractPainter();
	AbstractPainter.call( this );

	this.htmlDocumentation= '';

	this._addContentToDocument = function( content ) {
		this.htmlDocumentation += content;
	}

	this._addElementStartToDocument = function( elementName ) {
		this._addContentToDocument( '<' + elementName + '>' );
	}
	
	this._addElementEndToDocument = function( elementName ) {
		this._addContentToDocument( '</' + elementName + '>\r\n' );
	}

	this._addElementToDocument = function( elementName, content ) {
		this._addElementStartToDocument( elementName );
		this._addContentToDocument( content );
		this._addElementEndToDocument( elementName );
	}

	this._formatTestCaseName = function( unformattedTestCaseName ) {
		return unformattedTestCaseName;
	}

	this._formatTestMethodName = function( unformattedTestMethodName ) {
		return unformattedTestMethodName;
	}

	this.paintTestCaseStart   	= function() {
		this._addElementToDocument( 'H2', this._formatTestCaseName( this.tracker.getCurrentTestCase() ) );
		this._addElementStartToDocument( 'UL' );
	}
	
	this.paintTestCaseEnd   	= function() {
		this._addElementEndToDocument( 'UL' );
	}

	this.paintTestMethodStart	= function() {
		this._addElementToDocument( 'LI', this._formatTestMethodName( this.tracker.getCurrentTestMethod() ) );
	}
	
	this.paintTestSuiteStart   	= function() {
		this._addElementToDocument( 'H1', 'Generated Documentation' );
	}

	this.paintTestSuiteEnd     	= function() {
		var targetDiv = window.document.getElementById( 'Documentation' );
		if ( targetDiv ) targetDiv.innerHTML = this.htmlDocumentation;
	}

}